/**
*
* @brief Definition of CPhoneCallMaker
*
* Copyright (c) EMCC Software Ltd 2003
* @version 1.0
*/

#include "PhoneCallMaker.h"
#include "Logger.h"
_LIT(KTSY, "phonetsy");


CPhoneCallMaker::CPhoneCallMaker(MAnsPhoneCallMakerObserver& aObserver)
:CActive(EPriorityMore),
 iObserver(aObserver),
 iState(ENoState)
	{
	}

CPhoneCallMaker::~CPhoneCallMaker()
	{
	Cancel();
	TelCloseL();
	}

CPhoneCallMaker* CPhoneCallMaker::NewL(MAnsPhoneCallMakerObserver& aObserver)
	{
	CPhoneCallMaker* self = new (ELeave) CPhoneCallMaker(aObserver);
	CleanupStack::PushL(self);
	self->ConstructL();
	CleanupStack::Pop(self);
	return self;
	}

void CPhoneCallMaker::ConstructL()
	{
	CActiveScheduler::Add(this);
	
	}

///////////////////////////////////////////////////////////////////////////////////////////////////////
// CActive
//
///////////////////////////////////////////////////////////////////////////////////////////////////////

void CPhoneCallMaker::RunL()
	{
	// if the caller hangs up, then we will get KErrGeneral error here
	if(iState == EDialling && iStatus.Int() == KErrGeneral)
		{
		Stop();
		iObserver.HandleCallHungUpL();
		return;
		}

	if(iStatus.Int() != KErrNone)
		return;

	switch(iState)
		{
		case EDialling:
			iState = EWatching;
			StartL();
			break;

		case EWatching:
			User::LeaveIfError(iCall.GetStatus(iCallStatus));
			if(iCallStatus == RCall::EStatusHangingUp || iCallStatus == RCall::EStatusIdle)
				{
				Stop();
				iObserver.HandleCallHungUpL();
				}
			else
				{
				StartL();
				}
			break;

		default:
			break;
		}
	}

void CPhoneCallMaker::DoCancel()
	{
	Stop();
	}


void CPhoneCallMaker::MakeCallL(const TDesC& aNumber)
	{
	LOGCALL(TelStartL());
	iState = EDialling;
    iNumber.Copy(aNumber);
	StartL();
	}

void CPhoneCallMaker::StartL()
	{
	switch(iState)
		{
		case ENoState:
			return;
		case EDialling:
			{
			LOGCALL(User::LeaveIfError(iCall.OpenNewCall(iLine)));
			LOGCALL(iCall.Dial(iStatus, iNumber));
			break;
			}
		case EWatching:
			iCall.NotifyStatusChange(iStatus, iCallStatus);
			break;
		}
	SetActive();
	}

void CPhoneCallMaker::Stop()
	{
	switch(iState)
		{
		case ENoState:
			break;
		case EDialling:
			iCall.HangUp();
			iCall.Close();
			break;
		case EWatching:
			iCall.NotifyStatusChangeCancel();
			iCall.Close();
			break;
		}
	iState = ENoState;
	//LOGCALL(TelCloseL());
	}

void CPhoneCallMaker::TelStartL()
		// starts the telephony server and line;
		// this does not start up the call watcher
		// this is used when dialling
	{
		
		User::LeaveIfError(iSession.Connect());
		// load the appropriate tsy
		User::LeaveIfError(iSession.LoadPhoneModule(KTSY));

		// in order to get a handle on a line, we must get a handle on an RPhone object
		TInt numberPhones = 0;
		User::LeaveIfError(iSession.EnumeratePhones(numberPhones));
		if(!numberPhones)
			User::Leave(KErrNotFound);

		// we use the 1st available phone
		RTelServer::TPhoneInfo phoneInfo;
		User::LeaveIfError(iSession.GetPhoneInfo(0, phoneInfo));
		User::LeaveIfError(iPhone.Open(iSession, phoneInfo.iName));

		// we must now find a line that will accept voice calls
		TInt numberLines = 0;
		User::LeaveIfError(iPhone.EnumerateLines(numberLines));
		RPhone::TLineInfo lineInfo;
		TBool foundLine = EFalse;
		for(TInt a = 0; a < numberLines; a++)
		{
			User::LeaveIfError(iPhone.GetLineInfo(a, lineInfo));
			if(lineInfo.iLineCapsFlags & RLine::KCapsVoice)
			{
				foundLine = ETrue;
				break;
			}
		}

		if(!foundLine)
			User::Leave(KErrNotFound);

		User::LeaveIfError(iLine.Open(iPhone, lineInfo.iName));
	}

void CPhoneCallMaker::TelCloseL()
{
	iPhone.Close();
	iLine.Close();
	iSession.Close();
}